package com.fwtai.builder;

public final class DefaultBuilder implements IdGenerator{

  private static SnowWorker _SnowWorker = null;

  public DefaultBuilder(final IdWorkerOptions options) throws IdWorkerException{
    if (options == null) {
      throw new IdWorkerException("options参数不能为空.");
    }

    // 1.BaseTime
    if (options.BaseTime < 315504000000L || options.BaseTime > System.currentTimeMillis()) {
      throw new IdWorkerException("设置当前系统时间出错");
    }

    // 2.WorkerIdBitLength
    if (options.WorkerIdBitLength <= 0) {
      throw new IdWorkerException("WorkerIdBitLength 出错.(取值范围:[1, 21])");
    }
    if (options.WorkerIdBitLength + options.SeqBitLength > 22) {
      throw new IdWorkerException("错误：WorkerIdBitLength的值 + SeqBitLength的值应该 <= 22");
    }

    // 3.WorkerId
    int maxWorkerIdNumber = (1 << options.WorkerIdBitLength) - 1;
    if (maxWorkerIdNumber == 0) {
      maxWorkerIdNumber = 63;
    }
    if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) {
      throw new IdWorkerException(
        "WorkerId 出错. (取值范围:[0, " + (maxWorkerIdNumber > 0 ? maxWorkerIdNumber : 63) + "]");
    }

    // 4.SeqBitLength
    if (options.SeqBitLength < 2 || options.SeqBitLength > 21) {
      throw new IdWorkerException("SeqBitLength 出错. (取值范围:[2, 21])");
    }

    // 5.MaxSeqNumber
    int maxSeqNumber = (1 << options.SeqBitLength) - 1;
    if (maxSeqNumber == 0) {
      maxSeqNumber = 63;
    }
    if (options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber) {
      throw new IdWorkerException("MaxSeqNumber 出错. (取值范围:[1, " + maxSeqNumber + "]");
    }

    // 6.MinSeqNumber
    if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxSeqNumber) {
      throw new IdWorkerException("MinSeqNumber 出错. (取值范围:[5, " + maxSeqNumber + "]");
    }

    // 7.TopOverCostCount
    if (options.TopOverCostCount < 0 || options.TopOverCostCount > 10000) {
      throw new IdWorkerException("TopOverCostCount 出错. (取值范围:[0, 10000]");
    }

    switch (options.Method) {
      case 2:
        _SnowWorker = new IdWorkerBase(options);
        break;
      case 1:
      default:
        _SnowWorker = new IdWorkerOptimize(options);
        break;
    }

    if (options.Method == 1) {
      try {
        Thread.sleep(500);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }

  @Override
  public long getKey() {
    return _SnowWorker.nextId();
  }
}